﻿using System;
using System.Collections.Generic;
using System.Data.Objects.DataClasses;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using DomainModelGenerator.Properties;

namespace DomainModelGenerator
{
    public  class CodeGenerator : ICodeGenerator
    {
        private static readonly List<String> CommonFieldList = new List<String>() { "CREATED_BY", "CREATED_DATE", "UPDATED_BY", "UPDATED_DATE" };
        public const string LineFeed = "\r\n";
        public void GenerateDomainFiles(string fileName, Type type)
        {
            string val = string.Empty;
            val += DomainModelGenerator.Properties.Resources.Copyright;
            val += LineFeed;
            val += LineFeed;
            val += DomainModelGenerator.Properties.Resources.Using1;
            val += LineFeed;
            val += LineFeed;

            string domain1 = DomainModelGenerator.Properties.Resources.Domain1;
            string domain2 = DomainModelGenerator.Properties.Resources.Domain2;
            string tableName = type.ToString().Split('.')[type.ToString().Split('.').Length - 1];
            //string[] split = tableName.Split('_');

            //WmsUser
            string domainName1 = GetFormatProperty(tableName);
            //wmsUser
            string domainName2 = GetFormatVar(tableName);
       
            //domain1 = string.Format(domain1, domainName1, domainName2);
            domain1 = domain1.Replace("{0}", domainName1);
            domain1 = domain1.Replace("{1}", domainName2);

            val += domain1;
            val += LineFeed;
            val += LineFeed;

            domain2 = domain2.Replace("{0}", GetFormatProperty(tableName));

            string middle = LineFeed;
            PropertyInfo[] propertyInfos = type.GetProperties();
            foreach (var propertyInfo in propertyInfos)
            {
                if( propertyInfo.Name == "EntityKey" || CommonFieldList.Contains( propertyInfo.Name))
                {
                    continue;
                }
                //string UserId { get; set; }
                string regx = "        {0} {1}  { get; set; }" + LineFeed + LineFeed;
                if(propertyInfo.CanRead && propertyInfo.CanWrite)
                {
                    //string t = propertyInfo.GetType().ToString().Split('.')[propertyInfo.GetType().ToString().Split('.').Length - 1];
                    string t = propertyInfo.PropertyType.Name;
                    if (t == "Nullable`1")
                    {
                        //泛型引用类型
                        string typeName = propertyInfo.PropertyType.FullName.Split(new string[] {"[[","]]"},StringSplitOptions.None)[1];

                        typeName = typeName.Split(',')[0];
                        typeName = typeName.Split('.')[typeName.Split('.').Length - 1];

                        string r = "{0}?";
                        string k = string.Format(r, typeName);
                        string tmp = regx.Replace("{0}", k);
                        tmp = tmp.Replace("{1}", GetFormatProperty(propertyInfo.Name));
                        middle += tmp;
                        //fullName
                    }
                    else
                    {
                        string tmp = regx.Replace("{0}", t);
                        tmp = tmp.Replace("{1}", GetFormatProperty(propertyInfo.Name));
                        middle += tmp;
                    }
                }
            }
            //val += middle;
            domain2 = domain2.Replace("{1}", middle);
            string bottom = LineFeed;
          
            foreach (var propertyInfo in propertyInfos)
            {
                if (propertyInfo.Name == "EntityKey" || CommonFieldList.Contains(propertyInfo.Name))
                {
                    continue;
                }
                string regx = "        [DataFieldName(\"{2}\")]" + LineFeed + "        [DataMember]" + LineFeed + "        public {0} {1} { get; set; }" + LineFeed + LineFeed;
                if (propertyInfo.CanRead && propertyInfo.CanWrite)
                {
                    string t = propertyInfo.PropertyType.Name;
                    if (t == "Nullable`1")
                    {
                        //泛型引用类型
                        string typeName = propertyInfo.PropertyType.FullName.Split(new string[] { "[[", "]]" }, StringSplitOptions.None)[1];

                        typeName = typeName.Split(',')[0];
                        typeName = typeName.Split('.')[typeName.Split('.').Length - 1];

                        string r = "{0}?";
                        string k = string.Format(r, typeName);
                        string tmp = regx.Replace("{0}", k);
                        tmp = tmp.Replace("{1}", GetFormatProperty(propertyInfo.Name));
                        tmp = tmp.Replace("{2}", propertyInfo.Name);
                        bottom += tmp;
                    }
                    else
                    {
                        string tmp = regx.Replace("{0}", t);
                        tmp = tmp.Replace("{1}", GetFormatProperty(propertyInfo.Name));
                        tmp = tmp.Replace("{2}", propertyInfo.Name);
                        bottom += tmp;
                    }
                }
            }
            domain2 = domain2.Replace("{2}", bottom);
            val += domain2;

            string file = fileName + GetFormatProperty(tableName) + ".cs";
            using (var writer = new StreamWriter(file, false, Encoding.Unicode))
            {
                writer.WriteLine(val);
            }
          
            //return val;
        }

        private string GetFormatProperty(string val)
        {
            string[] split = val.Split('_');
            //WmsUser
            string domainName = string.Empty;

            for (int i = 0; i < split.Count(); i++)
            {
                string tmp = string.Empty;
            
                for (int c = 0; c < split[i].Length; c++)
                {
                    if (c == 0)
                    {
                        tmp += split[i][c].ToString().ToUpper();
                  
                    }
                    else
                    {
                        tmp += split[i][c].ToString().ToLower();
               
                    }
                }
                domainName += tmp;
             
            }
            return domainName;
        }

        private string GetFormatVar(string val)
        {
            string[] split = val.Split('_');
            //wmsUser
            string domainName2 = string.Empty;

            for (int i = 0; i < split.Count(); i++)
            {
              
                string tmp2 = string.Empty;
                for (int c = 0; c < split[i].Length; c++)
                {
                    if (c == 0)
                    {
                  
                        if (i == 0)
                        {
                            tmp2 += split[i][c].ToString().ToLower();
                        }
                        else
                        {
                            tmp2 += split[i][c].ToString().ToUpper();
                        }
                    }
                    else
                    {
                     
                        tmp2 += split[i][c].ToString().ToLower();
                    }
                }
             
                domainName2 += tmp2;
            }
            return domainName2;
        }

        public void GenerateServiceFile(string fileName, Type type)
        {
            string val = string.Empty;
            string tableName = type.ToString().Split('.')[type.ToString().Split('.').Length - 1];

            string service = DomainModelGenerator.Properties.Resources.Service;
            //service = string.Format(service, GetFormatProperty(tableName), GetFormatVar(tableName), tableName);
            service = service.Replace("{0}", GetFormatProperty(tableName));
            service = service.Replace("{1}", GetFormatVar(tableName));
            service = service.Replace("{2}", tableName);
            //算出主键列表
            var entityKeyList = new List<string>();
            PropertyInfo[] propertyInfos = type.GetProperties();
            foreach (var propertyInfo in propertyInfos)
            {
                var attriList = propertyInfo.GetCustomAttributes(typeof (EdmScalarPropertyAttribute), false);
                if (attriList.Count() > 0)
                {
                    var edmScalarPropertyAttribute = (EdmScalarPropertyAttribute) attriList[0];
                    if (edmScalarPropertyAttribute.EntityKeyProperty)
                    {
                        entityKeyList.Add(this.GetFormatProperty( propertyInfo.Name));
                    }
                }
            }
            string entityKeyValue = "";
            foreach (var entityKey in entityKeyList)
            {
                if (String.IsNullOrEmpty(entityKeyValue))
                {
                    entityKeyValue = ("\"" + entityKey + "\"");
                }
                else
                {
                    entityKeyValue += (" , \"" + entityKey + "\"");
                }
            }
            service = service.Replace("{3}", entityKeyValue);

            val += DomainModelGenerator.Properties.Resources.Copyright;
            val += LineFeed;
            val += LineFeed;
            val += service;
            string file = fileName + GetFormatProperty(tableName) + "ServiceSqlServer.cs";
            using (var writer = new StreamWriter(file, false, Encoding.Unicode))
            {
                writer.WriteLine(val);
            }
        }


        public string GenerateAbstract(Type type)
        {
            string tableName = type.ToString().Split('.')[type.ToString().Split('.').Length - 1];
            string result = Resource2.Abstract.Replace("{0}", GetFormatProperty(tableName));
            return result;
            
        }

        public string GenerateImpl( Type type)
        {
            string tableName = type.ToString().Split('.')[type.ToString().Split('.').Length - 1];
            string result = Resource2.Impl.Replace("{0}", GetFormatProperty(tableName));
            return result + CodeGenerator.LineFeed;
        }

        public string GenerateIServiceFacade( Type type)
        {
            string tableName = type.ToString().Split('.')[type.ToString().Split('.').Length - 1];
            string result = Resource2.IServiceFacade.Replace("{0}", GetFormatProperty(tableName));
            result = result.Replace("{1}", GetFormatVar(tableName));
            return result + CodeGenerator.LineFeed;
        }

        public string GenerateServiceFacade( Type type)
        {
            string tableName = type.ToString().Split('.')[type.ToString().Split('.').Length - 1];
            string result = Resource2.ServiceFacade.Replace("{0}", GetFormatProperty(tableName));
            result = result.Replace("{1}", GetFormatVar(tableName));
            return result + CodeGenerator.LineFeed;
        }
    }
}
